{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Using PS GPIO with PYNQ\n",
    "\n",
    "## Goal\n",
    "\n",
    "The aim of this notebook is to show how to use the Zynq PS GPIO from PYNQ. The PS GPIO are simple wires from the PS, and don't need a controller in the programmable logic. \n",
    "\n",
    "Up to 64 PS GPIO are available, and they can be used to connect simple control and data signals to IP or peripherals in the PL. \n",
    "\n",
    "\n",
    "## Hardware design\n",
    "\n",
    "This example uses a bitstream that connects PS GPIO to the LEDs, buttons, and switches and can be used with the PYNQ-Z1 or PYNQ-Z2 board. \n",
    "\n",
    "![PS GPIO Design](./images/ps_gpio_design.png \"PS GPIO Design\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### GPIO Map\n",
    "\n",
    "|  GPIO | Peripheral |\n",
    "|-------|------------|\n",
    "| 0 - 3 | Buttons    |\n",
    "| 4 - 5 | Switches   |\n",
    "| 6 - 9 | LEDs       |"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 1. Download the tutorial overlay\n",
    "\n",
    "The `ps_gpio.bit` and `ps_gpio.hwh` files can be found in the bitstreams directory local to this folder. The .tcl file that can be used to rebuild the block diagram can also be found in this folder. \n",
    "The bitstream can be downloaded by passing the relative path to the Overlay class. "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* Check the bitstream and .tcl exists in the bitstream directory"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "!dir ./bitstream/ps_gpio.*"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* Download the bitstream"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from pynq import Overlay\n",
    "ps_gpio_design = Overlay(\"./bitstream/ps_gpio.bit\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## GPIO class\n",
    "\n",
    "The GPIO class will be used to access the PS GPIO. "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 1. Controlling the switches and push-buttons\n",
    "\n",
    "In the design PS GPIO pins 0 to 3 are connected to the pushbuttons, and pins 4 to 5 are connected to the dip-switches on the PYNQ-Z1 and PYNQ-Z2 boards. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from pynq import GPIO\n",
    "\n",
    "button0 = GPIO(GPIO.get_gpio_pin(0), 'in')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "button0.read()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Try pressing the button BTN0 on the board and rerunning the cell above."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The other buttons and switches can be read in a similar way. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "button1 = GPIO(GPIO.get_gpio_pin(1), 'in')\n",
    "button2 = GPIO(GPIO.get_gpio_pin(2), 'in')\n",
    "button3 = GPIO(GPIO.get_gpio_pin(3), 'in')\n",
    "\n",
    "switch0 = GPIO(GPIO.get_gpio_pin(4), 'in')\n",
    "switch1 = GPIO(GPIO.get_gpio_pin(5), 'in')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Try pressing different buttons (BTN1, BTN2, BTN3), and moving the switches (SW0, SW1) while executing the cell below. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print(f\"Button0: {button0.read()}\")\n",
    "print(f\"Button1: {button1.read()}\")\n",
    "print(f\"Button2: {button2.read()}\")\n",
    "print(f\"Button3: {button3.read()}\")\n",
    "\n",
    "print(\"\")\n",
    "print(f\"Switch0: {switch0.read()}\")\n",
    "print(f\"Switch1: {switch1.read()}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2. Controlling the LEDs\n",
    "\n",
    "The LEDs can be used in a similar way, the only difference is the direction passed to the GPIO class. The LEDs are connected to PS GPIO 6 to 9 in the design we are using. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "led0 = GPIO(GPIO.get_gpio_pin(6), 'out')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "led0.write(1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "led1 = GPIO(GPIO.get_gpio_pin(7), 'out')\n",
    "led2 = GPIO(GPIO.get_gpio_pin(8), 'out')\n",
    "led3 = GPIO(GPIO.get_gpio_pin(9), 'out')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from time import sleep\n",
    "\n",
    "led1.write(1)\n",
    "sleep(1)\n",
    "led2.write(1)\n",
    "sleep(1)\n",
    "led3.write(1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Turn off the LEDs"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "led0.write(0)\n",
    "led1.write(0)\n",
    "led2.write(0)\n",
    "led3.write(0)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3 putting it together\n",
    "\n",
    "Run a loop to set the LEDs to the value of the pushbuttons. \n",
    "\n",
    "Before executing the next cell, make sure Switch 0 (SW0) is \"on\". While the loop is running, press a push-button and notice the corresponding LED turns on. To exit the loop, change Switch 0 to off. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "while(switch0.read() == 1):\n",
    "    led0.write(button0.read())\n",
    "    led1.write(button1.read())\n",
    "    led2.write(button2.read())\n",
    "    led3.write(button3.read())    "
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
